/* Copyright ©北京微利宝信息技术有限公司 right reserved.*/

package com.wlb365.doc.cfca;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Hex;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.Security;
import java.security.spec.InvalidKeySpecException;

/**
 * <p>
 * 概述： DESede工具,有问题请咨询研发团队
 * 集成，请遵循jdk标准规范，jdk官方关于安全升级，请及时升级版本
 * 注：三方工具慎用，考虑升级等方便造成的问题！本工具用BC集成
 * </p>
 *
 * @author 创建人：    ryl
 * @copyRight 所有权©：  北京微利宝信息技术有限公司  All right reserved.
 * @date 创建时间：2019年2月8日 下午2:47:22
 */
@Slf4j
public class BCDESedeUtils {
    /**
     * 206 为是事业部名称为：供应链金融事业部的时间，共计206天，隶属北京微利宝-wlb
     * 盐
     */
    private static final String DEFAULT_DES_EDE_PADDING = "DESede/ECB/PKCS5Padding";
    private static final String WLB_SALT = "wlb[206]";
    private static final String DEFAULT_DES_EDE_KEY = "dc3edf85a71a9e45852968add002f702924ccdf7540ef146";
    private static final String CRYPTO_ALGORITHM = "DESede";

    /**
     * 初始化一个 key
     *
     * @return
     * @throws Exception
     */
    private static byte[] getKey() throws Exception {
        //生成key
        byte[] key = new byte[0];
        try {
            //通过改变provider的方式，其他操作一样
            Security.addProvider(new BouncyCastleProvider());

            //生成key
            KeyGenerator keyGenerator = KeyGenerator.getInstance(CRYPTO_ALGORITHM);
            keyGenerator.init(new SecureRandom());
            //生成key的材料
            SecretKey secretKey = keyGenerator.generateKey();
            key = secretKey.getEncoded();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return key;
    }

    /**
     * 初始化一个加密用的key
     *
     * @param key
     * @return
     * @throws Exception
     */
    private static SecretKey initKey(byte[] key) throws Exception {
        //key转换成密钥
        SecretKey resultKey = null;
        //转换后的密钥
        try {
            DESedeKeySpec desKeySpec = new DESedeKeySpec(key);
            SecretKeyFactory factory = SecretKeyFactory.getInstance(CRYPTO_ALGORITHM);
            resultKey = factory.generateSecret(desKeySpec);
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (InvalidKeySpecException e) {
            e.printStackTrace();
        }
        return resultKey;
    }

    /**
     * <p>
     * 概述： 加密
     * 十六进制
     * </p>
     *
     * @param arg
     * @return String
     * @author ryl
     * @date 2018年11月6日 上午10:59:00
     */
    public static String desedeEncryptHex(String arg) throws Exception {
        try {
            //算法类型/工作方式/填充方式
            Cipher cipher = Cipher.getInstance(DEFAULT_DES_EDE_PADDING);
            //指定为加密模式
            cipher.init(Cipher.ENCRYPT_MODE, initKey(DEFAULT_DES_EDE_KEY.getBytes()));
            byte[] result = cipher.doFinal(arg.getBytes(StandardCharsets.UTF_8));
            return Hex.encodeHexString(result);
        } catch (Exception e) {
            log.error("加密失败", e);
            e.printStackTrace();
        }
        return "";
    }

    /**
     * <p>
     * 概述： 加密
     * 十六进制
     * </p>
     *
     * @param arg
     * @return String
     * @author ryl
     * @date 2018年11月6日 上午10:59:00
     */
    public static String desedeEncryptHex(String arg, String secret) throws Exception {
        try {
            //算法类型/工作方式/填充方式
            Cipher cipher = Cipher.getInstance(DEFAULT_DES_EDE_PADDING);
            //指定为加密模式
            cipher.init(Cipher.ENCRYPT_MODE, initKey(secret.getBytes()));
            byte[] result = cipher.doFinal(arg.getBytes(StandardCharsets.UTF_8));
            return Hex.encodeHexString(result);
        } catch (Exception e) {
            log.error("加密失败", e);
            e.printStackTrace();
        }
        return "";
    }

    /**
     * <p>
     * 概述： 解密
     * </p>
     *
     * @param enArg
     * @return String
     * @author ryl
     * @date 2018年11月6日 上午10:59:46
     */
    public static String desedeDecryptStr(String enArg) {
        try {
            //算法类型/工作方式/填充方式
            Cipher cipher = Cipher.getInstance(DEFAULT_DES_EDE_PADDING);
            //相同密钥，指定为解密模式
            cipher.init(Cipher.DECRYPT_MODE, initKey(DEFAULT_DES_EDE_KEY.getBytes()));
            //根据加密内容解密
            byte[] result = cipher.doFinal(Hex.decodeHex(enArg));
            return new String(result, StandardCharsets.UTF_8);
        } catch (Exception e) {
            log.error("解密异常", e);
            e.printStackTrace();
        }
        return "";
    }

    /**
     * <p>
     * 概述： 解密
     * </p>
     *
     * @param enArg
     * @return String
     * @author ryl
     * @date 2018年11月6日 上午10:59:46
     */
    public static String desedeDecryptStr(String enArg, String secret) {
        try {
            //算法类型/工作方式/填充方式
            Cipher cipher = Cipher.getInstance(DEFAULT_DES_EDE_PADDING);
            //相同密钥，指定为解密模式
            cipher.init(Cipher.DECRYPT_MODE, initKey(secret.getBytes()));
            //根据加密内容解密
            byte[] result = cipher.doFinal(Hex.decodeHex(enArg));
            return new String(result, StandardCharsets.UTF_8);
        } catch (Exception e) {
            log.error("解密异常", e);
            e.printStackTrace();
        }
        return "";
    }

//	@Test
//	public void desdeTest() throws Exception {
//		String value="wlb";
//		System.out.println("明文: "+value);
//		//加密
//		String result1=desedeEncryptHex(value);
//		System.out.println("3DES加密: "+result1);
//
//		//解密
//		String result2=desedeDecryptStr(result1);
//		System.out.println("3DES解密: "+result2);
//		System.out.println("解密结果: "+result2.equals(value));
//	}
}
